﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using Microsoft.Windows.Controls.Ribbon;

namespace MC34063_Universal_Calculator
{
    /// <summary>
    /// Interaktionslogik für Parameters.xaml
    /// </summary>
    [Serializable]
    public partial class ParametersPage : Page
    {
        enum Faded { In = 1, Out = 2, Unknown = 0 };
        bool _useDefaultParts = true;
        bool _updownSliderOut = false;
        InputData _inputData = new InputData();
        OutputData _outputData;
        OutputData.RegulatorType _currentRegType = OutputData.RegulatorType.NONE;
        Page _schematicPage = null;

        public Page SchematicPage
        {
            get { return _schematicPage; }
            set { _schematicPage = value; }
        }
        public event RoutedEventHandler SchematicClick;

        public OutputData.RegulatorType CurrentRegType
        {
            get { return _currentRegType; }
            set { _currentRegType = value; }
        }

        public ParametersPage()
        {
            InitializeComponent();
            _outputData = new OutputData(ref _inputData);
            spInput.DataContext = _inputData;
            _inputData.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_inputData_PropertyChanged);
            _outputData.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_outputData_PropertyChanged);
            _inputData.UpDownSwitch += new InputData.UpDownSwitchHandler(_inputData_UpDownSwitch);
            spOutput.DataContext = _outputData;
        }

        private void FadeControl(Control ctrl, bool inout)
        {
            if (inout)
            {
                Storyboard fadeCalcNotValid = (Storyboard)FindResource("FadeIn");
                fadeCalcNotValid.SetValue(Storyboard.TargetNameProperty, ctrl.Name);
                fadeCalcNotValid.Begin();
            }
            else
            {
                Storyboard fadeCalcNotValid = (Storyboard)FindResource("FadeOut");
                fadeCalcNotValid.SetValue(Storyboard.TargetNameProperty, ctrl.Name);
                fadeCalcNotValid.Begin();
            }
        }

        private void FadeControl(Decorator ctrl, bool inout)
        {
            if (inout)
            {
                Storyboard fadeCalcNotValid = (Storyboard)FindResource("FadeIn");
                fadeCalcNotValid.SetValue(Storyboard.TargetNameProperty, ctrl.Name);
                fadeCalcNotValid.Begin();
            }
            else
            {
                Storyboard fadeCalcNotValid = (Storyboard)FindResource("FadeOut");
                fadeCalcNotValid.SetValue(Storyboard.TargetNameProperty, ctrl.Name);
                fadeCalcNotValid.Begin();
            }
        }

        bool IsFadedIn(Control ctrl)
        {
            if (ctrl.Tag == null)
                ctrl.Tag = Faded.Unknown;
            if ((Faded)Enum.Parse(typeof(Faded), ctrl.Tag.ToString(), true) == Faded.In)
                return true;
            else
                return false;
        }

        bool IsFadedIn(Decorator ctrl)
        {
            if (ctrl.Tag == null)
                ctrl.Tag = Faded.Unknown;
            if ((Faded)Enum.Parse(typeof(Faded), ctrl.Tag.ToString(), true) == Faded.In)
                return true;
            else
                return false;
        }

        BitmapImage GetImageResource(string resourcePath)
        {
            BitmapImage img = new BitmapImage();
            img.BeginInit();
            img.UriSource = new Uri("pack://application:,,," + resourcePath);
            img.EndInit();

            return img;
        }

        string GetLocalizedValue(string resourcePath)
        {
            string tmp = "";
            new WPFLocalizeExtension.Extensions.LocTextExtension(resourcePath).ResolveLocalizedValue(out tmp);
            return tmp;
        }

        void _inputData_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            InputData inpData = (InputData)sender;
            if(!IsFadedIn(lblCalcNotValid))
            {
                FadeControl(lblCalcNotValid, true);
                lblCalcNotValid.Tag = Faded.In;
            }

            if (e.PropertyName == "Vinmax" || e.PropertyName == "Vinmin")
            {
                bool vminsvmax = inpData.Vinmax < inpData.Vinmin;
                bool vminnegvmaxpos = inpData.Vinmin < 0 && inpData.Vinmax > 0;
                bool vintoobig = inpData.Vinmax > inpData.SelectedICValue.MaxVin;

                if (vminsvmax || vminnegvmaxpos || vintoobig)
                {
                    FadeControl(bgVinMax, true);
                    FadeControl(bgVinMin, true);
                    RibbonToolTip tt = new RibbonToolTip();
                    tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/error_32.png");
                    string output = "";

                    new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:vinerror").SetBinding(tt, RibbonToolTip.TitleProperty);

                    if (vminsvmax)
                    {
                        output += GetLocalizedValue("MC34063_Universal_Calculator:Global:vminsvmax") + "\n";
                    }
                    if (vminnegvmaxpos)
                    {
                        output += GetLocalizedValue("MC34063_Universal_Calculator:Global:vminnegvmaxpos") + "\n";
                    }
                    if (vintoobig)
                    {
                        output += GetLocalizedValue("MC34063_Universal_Calculator:Global:vintoobig1") + inpData.SelectedICValue.MaxVin.ToString() + "V" + GetLocalizedValue("MC34063_Universal_Calculator:Global:vintoobig2") + "\n";
                    }

                    tt.Description = output.Trim();

                    bgVinMax.ToolTip = bgVinMin.ToolTip = tt;

                    btnCalculate.IsEnabled = false;

                    bgVinMax.Tag = bgVinMin.Tag = Faded.In;
                }
                else if (IsFadedIn(bgVinMax) || IsFadedIn(bgVinMin))
                {
                    FadeControl(bgVinMax, false);
                    FadeControl(bgVinMin, false);
                    bgVinMin.ToolTip = bgVinMax.ToolTip = null;
                    btnCalculate.IsEnabled = true;
                    bgVinMax.Tag = bgVinMin.Tag = Faded.Out;
                }
            }

            if (e.PropertyName == "Vout" || e.PropertyName == "DiodeVf" || e.PropertyName == "Vinmax")
            {
                bool isInverter = ((inpData.Vinmin > 0) && (inpData.Vout < 0)) || ((inpData.Vinmin < 0) && (inpData.Vout > 0));
                bool overMaxVout = (isInverter) ? ((inpData.Vinmax + inpData.DiodeVf + Math.Abs(inpData.Vout)) > inpData.SelectedICValue.MaxVQ) : (inpData.Vout > inpData.SelectedICValue.MaxVQ);
                bool dangerousVout = Math.Abs(inpData.Vout) > 60;

                if (overMaxVout)
                {
                    RibbonToolTip tt = new RibbonToolTip();
                    string output = "";

                    if (isInverter)
                    {
                        bgVout.Background = (Brush)FindResource("BGError");
                        btnCalculate.IsEnabled = false;
                        new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:vouterror").SetBinding(tt, RibbonToolTip.TitleProperty);
                        tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/error_32.png");
                        output += GetLocalizedValue("MC34063_Universal_Calculator:Global:voutinvtohigh1") + inpData.SelectedICValue.MaxVQ.ToString() + "V" + GetLocalizedValue("MC34063_Universal_Calculator:Global:voutinvtohigh2") + "\n";
                    }
                    else
                    {
                        bgVout.Background = (Brush)FindResource("BGWarning");
                        new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:voutwarning").SetBinding(tt, RibbonToolTip.TitleProperty);
                        if (dangerousVout)
                        {
                            tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/highvoltage_32.png");
                            output += "\n\n" + GetLocalizedValue("MC34063_Universal_Calculator:Global:dangerousVoltageWarning") + "\n\n";
                        }
                        else
                        {
                            tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/warning_32.png");
                        }
                        btnCalculate.IsEnabled = true;
                        output += GetLocalizedValue("MC34063_Universal_Calculator:Global:voltageNoInternalQ") + "\n";
                    }

                    tt.Description = output.Trim();
                    bgVout.ToolTip = tt;
                    FadeControl(bgVout, true);
                    bgVout.Tag = Faded.In;
                }
                else if(IsFadedIn(bgVout))
                {
                    FadeControl(bgVout, false);
                    bgVout.ToolTip = null;
                    bgVout.Tag = Faded.Out;
                    btnCalculate.IsEnabled = true;
                }
            }
            if (e.PropertyName == "Fmax" || e.PropertyName == "Frequency")
            {
                bool freqtoohigh = inpData.Frequency > inpData.Fmax;

                if (freqtoohigh)
                {
                    FadeControl(bgFrequency, true);

                    RibbonToolTip tt = new RibbonToolTip();
                    tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/error_32.png");
                    string output = "";

                    new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:frequencyerror").SetBinding(tt, RibbonToolTip.TitleProperty);

                    output += GetLocalizedValue("MC34063_Universal_Calculator:Global:frequencytoohigh1") + inpData.Fmax.ToString() + "Hz" + GetLocalizedValue("MC34063_Universal_Calculator:Global:frequencytoohigh2") + "\n";
                    tt.Description = output.Trim();
                    btnCalculate.IsEnabled = false;
                    bgFrequency.ToolTip = tt;
                    bgFrequency.Tag = Faded.In;
                }
                else if(IsFadedIn(bgFrequency))
                {
                    FadeControl(bgFrequency, false);
                    bgFrequency.Tag = Faded.Out;
                    bgFrequency.ToolTip = null;
                    btnCalculate.IsEnabled = true;
                }
            }

            if (e.PropertyName == "IDiv" || e.PropertyName == "Ioutmax")
            {
                bool idivtoolarge = inpData.IDiv * 1E-6 / inpData.Ioutmax > 0.01;
                bool idivtoosmall = inpData.IDiv < 100;

                if (idivtoolarge || idivtoosmall)
                {
                    FadeControl(bgIdiv, true);

                    RibbonToolTip tt = new RibbonToolTip();
                    tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/warning_32.png");
                    string output = "";

                    if(idivtoolarge)
                        new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:idivwarninghigh").SetBinding(tt, RibbonToolTip.TitleProperty);
                    else
                        new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:idivwarninglow").SetBinding(tt, RibbonToolTip.TitleProperty);

                    output += GetLocalizedValue("MC34063_Universal_Calculator:Global:idivwarningcomment") + "\n";
                    tt.Description = output.Trim();
                    bgIdiv.ToolTip = tt;
                    bgIdiv.Tag = Faded.In;
                }
                else if (IsFadedIn(bgIdiv))
                {
                    FadeControl(bgIdiv, false);
                    bgIdiv.Tag = Faded.Out;
                    bgIdiv.ToolTip = null;
                }
            }
        }

        void _outputData_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            OutputData outData = (OutputData)sender;

            if (e.PropertyName == "Ipeak")
            {
                if (Math.Abs(outData.Ipeak) > _inputData.SelectedICValue.MaxIsw)
                {
                    FadeControl(bgIpeak, true);

                    RibbonToolTip tt = new RibbonToolTip();
                    tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/warning_32.png");
                    string output = "";

                    new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:ipeaktoohigh").SetBinding(tt, RibbonToolTip.TitleProperty);

                    output += GetLocalizedValue("MC34063_Universal_Calculator:Global:ipeaktoohighcomment") + "\n";
                    tt.Description = output.Trim();
                    bgIpeak.ToolTip = tt;

                    bgIpeak.Tag = Faded.In;
                }
                else if(IsFadedIn(bgIpeak))
                {
                    FadeControl(bgIpeak, false);
                    bgIpeak.Tag = Faded.Out;
                    bgIpeak.ToolTip = null;
                }
            }

            if (e.PropertyName == "MaxESR")
            {
                if (outData.MaxESR < 0.001)
                {
                    FadeControl(bgMaxESR, true);

                    RibbonToolTip tt = new RibbonToolTip();
                    tt.ImageSource = GetImageResource("/MC34063_Universal_Calculator;component/Images/warning_32.png");
                    string output = "";

                    new WPFLocalizeExtension.Extensions.LocTextExtension("MC34063_Universal_Calculator:Global:maxesrtoolow").SetBinding(tt, RibbonToolTip.TitleProperty);

                    output += GetLocalizedValue("MC34063_Universal_Calculator:Global:maxesrcomment") + "\n";
                    tt.Description = output.Trim();
                    bgMaxESR.ToolTip = tt;

                    bgMaxESR.Tag = Faded.In;
                }
                else if (IsFadedIn(bgMaxESR))
                {
                    FadeControl(bgMaxESR, false);
                    bgMaxESR.Tag = Faded.Out;
                    bgMaxESR.ToolTip = null;
                }
            }
        }

        void _inputData_UpDownSwitch(object sender, bool isUpDown)
        {
            if (isUpDown)
            {
                if (!_updownSliderOut)
                {
                    Storyboard slideVsat2 = (Storyboard)FindResource("SlideVsat2In");
                    slideVsat2.Begin();
                    Storyboard slideDiode2Vf = (Storyboard)FindResource("SlideDiode2VfIn");
                    slideDiode2Vf.Begin();
                    _updownSliderOut = true;
                }
            }
            else
            {
                Storyboard slideVsat2 = (Storyboard)FindResource("SlideVsat2Out");
                slideVsat2.Begin();
                Storyboard slideDiode2Vf = (Storyboard)FindResource("SlideDiode2VfOut");
                slideDiode2Vf.Begin();
                _updownSliderOut = false;
            }
        }

        public bool UseDefaultParts
        {
            get
            {
                return _useDefaultParts;
            }
            set
            {
                _useDefaultParts = value;
                if (!IsFadedIn(lblCalcNotValid))
                {
                    FadeControl(lblCalcNotValid, true);
                    lblCalcNotValid.Tag = Faded.In;
                }
            }
        }

        private void btnCalculate_Click(object sender, RoutedEventArgs e)
        {
            if (IsFadedIn(lblCalcNotValid))
            {
                FadeControl(lblCalcNotValid, false);
                lblCalcNotValid.Tag = Faded.Out;
            }
            OutputData.RegulatorType prevRegType = _currentRegType;
            _currentRegType = _outputData.Calculate(_inputData, _useDefaultParts);
            switch (_currentRegType)
            {
                case OutputData.RegulatorType.UP:
                    {
                        if (prevRegType != OutputData.RegulatorType.UP)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRdriverIn");
                            slideRdriver.Begin();
                        }
                        if (prevRegType == OutputData.RegulatorType.UP_DOWN)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRBiasOut");
                            slideRdriver.Begin();
                        }
                        System.Windows.Media.Animation.Storyboard sb = (System.Windows.Media.Animation.Storyboard)FindResource("SlideRdriverIn");
                        sb.Begin();
                        _schematicPage = new MC34063A_StepUp_Page(_outputData, _inputData);
                        schematicFrame.Navigate(_schematicPage);
                    }
                    break;

                case OutputData.RegulatorType.DOWN:
                    {
                        if (prevRegType == OutputData.RegulatorType.UP)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRdriverOut");
                            slideRdriver.Begin();
                        }
                        if (prevRegType == OutputData.RegulatorType.UP_DOWN)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRBiasOut");
                            slideRdriver.Begin();
                        }
                        _schematicPage = new MC34063A_StepDown_Page(_outputData, _inputData);
                        schematicFrame.Navigate(_schematicPage);
                    }
                    break;

                case OutputData.RegulatorType.INVERT:
                    {
                        if (prevRegType == OutputData.RegulatorType.UP)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRdriverOut");
                            slideRdriver.Begin();
                        }
                        if (prevRegType == OutputData.RegulatorType.UP_DOWN)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRBiasOut");
                            slideRdriver.Begin();
                        }
                        _schematicPage = new MC34063A_Invert_Page(_outputData, _inputData);
                        schematicFrame.Navigate(_schematicPage);
                    }
                    break;

                case OutputData.RegulatorType.UP_DOWN:
                    {
                        if (prevRegType == OutputData.RegulatorType.UP)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRdriverOut");
                            slideRdriver.Begin();
                        }
                        if (prevRegType != OutputData.RegulatorType.UP_DOWN)
                        {
                            Storyboard slideRdriver = (Storyboard)FindResource("SlideRBiasIn");
                            slideRdriver.Begin();
                        }
                        _schematicPage = new MC34063A_StepUpDown_Page(_outputData, _inputData);
                        schematicFrame.Navigate(_schematicPage);
                    }
                    break;
            }
        }

        private void schematicFrame_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if(e.LeftButton == MouseButtonState.Pressed)
                if (SchematicClick != null)
                    SchematicClick(this, new RoutedEventArgs());
        }

        public void UpdateSchematicFrame()
        {
            schematicFrame.Refresh();
        }

        public void Clear()
        {
            OutputData newOutData = new OutputData();
            InputData newInputData = new InputData();

            foreach (System.Reflection.PropertyInfo propInfo in typeof(InputData).GetProperties())
            {
                if (propInfo.CanWrite)
                {
                    if(!propInfo.PropertyType.IsArray && !propInfo.PropertyType.Name.ToUpper().Contains("COLLECTION"))
                        propInfo.SetValue(_inputData, propInfo.GetValue(newInputData, null), null);
                }
            }

            foreach (System.Reflection.PropertyInfo propInfo in typeof(OutputData).GetProperties())
            {
                if (propInfo.CanWrite)
                {
                    if (!propInfo.PropertyType.IsArray && !propInfo.PropertyType.Name.ToUpper().Contains("COLLECTION"))
                        propInfo.SetValue(_outputData, propInfo.GetValue(newOutData, null), null);
                }
            }

            FadeControl(bgMaxESR, false);
            bgMaxESR.Tag = Faded.Out;
            bgMaxESR.ToolTip = null;
        }
    }
}
